//
//  HUD+Popup.swift
//  BWHUDKit
//
//  Created by zhuxuhong on 2022/3/21.
//

import UIKit
import BWToolKit
import BWPopupView

extension HUD {
    public static func popup(
        sender: UIView,
        customView: UIView,
        arrow: Popup.ArrowDirection = .any,
        duration: TimeInterval = .infinity
    ) {
        show(.popup(.init(senderView: sender, icon: nil, text: nil, action: nil, arrow: arrow, customView: customView, duration: duration, maskColor: .clear)))
    }
    
    public static func popup(
        sender: UIView,
        icon: UIImage?,
        text: String?,
        action: Popup.Action? = nil
    ) {
        show(.popup(.init(senderView: sender, icon: icon, text: text, action: action, arrow: .any, customView: nil, duration: .infinity, maskColor: .clear)))
    }
    
    public static func popup(
        sender: UIView,
        rect: CGRect? = nil,
        icon: UIImage?,
        text: String?,
        action: Popup.Action? = nil,
        arrow: Popup.ArrowDirection = .any,
        duration: TimeInterval = 0
    ) {
        show(.popup(.init(senderView: sender, senderRect: rect, icon: icon, text: text, action: action, arrow: arrow, customView: nil, duration: duration, maskColor: .clear)))
    }
    
    static func showPopup(
        _ value: HUD.Popup,
        completion: BlockVoid? = nil
    ) -> UIViewController? {
        
        if value.senderView == nil && value.senderRect == nil {
            fatalError("You must provide at leat one of `sender view` or `sender rect` for popup showing!!!")
        }
        
        let configure = BWPopup(senderRect: value.senderRect, senderView: value.senderView, arrowDirection: value.arrow.toPopupArrowDirection, backgroundColor: value.backgroundColor, margin: 10, contentInsets: .with(all: 10), blockable: value.blockable, maskColor: value.maskColor, cornerRadius: 10, arrowSize: .bw_with(both: 10))
        
        if let customView = value.customView {
            return BWPopup.show(view: customView, configure: configure)
        }
        
        let vc = HUDPopupVC(hud: value, completion: completion)
        /// 1. Calling `vc.view` will trigger `vc.viewDidLoad()` to setup the popup contents;
        /// 2. Calling `vc.view.layoutIfNeeded()` will trigger uiview's auto layouts updating to
        ///    calculate `wrapperView's` frame size;
        if vc.view != nil, let view = vc.wrapperView {
            vc.view.layoutIfNeeded()
            let size = view.frame.size
            configure.popupSize.width = size.width + configure.contentInsets.left + configure.contentInsets.right
            configure.popupSize.height = size.height + configure.contentInsets.top + configure.contentInsets.bottom
        }
        
        return BWPopup.show(controller: vc, configure: configure)
    }
}


extension HUD {
    public class Popup: HUD.Data {
        var senderView: UIView?
        var senderRect: CGRect?
        var action: Action?
        var arrow: ArrowDirection
        var backgroundColor: UIColor
        
        public init(
            senderView: UIView? = nil,
            senderRect: CGRect? = nil,
            icon: UIImage? = nil,
            text: String? = nil,
            action: Action? = nil,
            arrow: ArrowDirection = .any,
            customView: UIView? = nil,
            duration: TimeInterval = .infinity,
            blockable: Bool = true,
            maskColor: UIColor = .clear,
            backgroundColor: UIColor = .black
        ) {
            self.backgroundColor = backgroundColor
            self.senderView = senderView
            self.senderRect = senderRect ?? senderView?.frame
            self.action = action
            self.arrow = arrow
            var d = (duration>0 || duration.isInfinite) ? duration : Duration.fit(text: text)
            if action?.title != nil || action?.icon != nil {
                d = .infinity
            }
            super.init(icon: icon, text: text, customView: customView, duration: d, maskColor: maskColor, blockable: blockable, position: .top)
        }
        
        public enum ArrowDirection {
            case any, up, down, left, right
            
            var toPopupArrowDirection: BWArrowDirection {
                switch self {
                case .any: return .any
                case .up: return .up
                case .down: return .down
                case .left: return .left
                case .right: return .right
                }
            }
        }
        
        public struct Action {
            var title: String?
            var icon: UIImage?
            var handler: BlockVoid?
            public init(title: String?, icon: UIImage?, handler: BlockVoid?) {
                self.title = title
                self.icon = icon
                self.handler = handler
            }
        }
    }
}
